package com.gitee.wsl.android.ui.ext

import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.os.Build
import android.view.View
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleOwner
import com.gitee.wsl.android.ext.intentOf
import com.gitee.wsl.coroutines.strategy.twiceCheckDelayCallBack
import android.app.Application
import android.content.Intent
import android.os.Bundle
import android.os.Process
import androidx.activity.FullyDrawnReporter
import androidx.activity.reportWhenComplete
import com.gitee.wsl.android.ext.ApplicationInit.application
import com.gitee.wsl.ext.K
import com.gitee.wsl.jvm.task.thread.Scheduler
import timber.log.Timber
import java.io.Serializable
import kotlin.reflect.KClass
import kotlin.system.exitProcess


/*fun ComponentActivity.pressBackTwiceToExitApp(toastText: String, delayMillis: Long = 2000, owner: LifecycleOwner = this) =
    pressBackTwiceToExitApp(delayMillis, owner) { toast(toastText) }

fun ComponentActivity.pressBackTwiceToExitApp(@StringRes toastText: Int, delayMillis: Long = 2000, owner: LifecycleOwner = this) =
    pressBackTwiceToExitApp(delayMillis, owner) { toast(toastText) }*/


/**
 * Activity管理任务栈，内部通过[Application.registerActivityLifecycleCallbacks]实现，可以打开和关闭指定
 * Activity，关闭所有Activity，关闭除指定Activity外所有Activity，终止进程等功能.
 * @author Ayvytr ['s GitHub](https://github.com/Ayvytr)
 * @since 3.1.6
 * 1. 修改[isForeground]，适配Android12最后关闭的Activity默认不会onDestroy()的问题
 * 2. [registerCallback]增加第二个参数observer，回调判断Activity是否前台可见
 * 3. 适配：不停的按返回很快关闭多个Activity时，Activity关闭/销毁顺序和正常顺序相反的问题
 *
 * @since 2.5.1
 */
object ActivityStack {
    /**
     * 应用是否运行在前台的监听器，注意：只关注Activity是否在前台可见.
     */
    @JvmStatic
    private lateinit var foregroundObserver: (Boolean) -> Unit

    @JvmStatic
    private var isForceClose: Boolean = false

    private var isInited:Boolean = false

    /**
     * 已创建，但是没销毁的Activity map.
     *
     * 注意：
     * 1. android12变更：关闭最后一个Activity后，默认不会调用onDestroy()
     * 2. 不停的按返回很快关闭多个Activity时，它们结束的顺序正好反了，最先打开的Activity走了onStop，但是
     * 没走onDestroy, 后面的Activity是从前往后依次销毁的
     *
     * Boolean: Activity是不是on stopped
     */
    @JvmStatic
    private val activityMap by lazy {
        LinkedHashMap<Activity, Boolean>()
    }

    @JvmStatic
    private val callback by lazy {
        object: Application.ActivityLifecycleCallbacks {
            override fun onActivityPaused(activity: Activity) {
            }

            override fun onActivityResumed(activity: Activity) {
            }

            override fun onActivityStarted(activity: Activity) {
                if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.isEmpty() && !com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.contains(activity)) {
                    com.gitee.wsl.android.ui.ext.ActivityStack.activityMap[activity] = false
                    com.gitee.wsl.android.ui.ext.ActivityStack.foregroundObserver.invoke(true)
                }
            }

            override fun onActivityDestroyed(activity: Activity) {
                com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.remove(activity)
                if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.isEmpty()) {
                    com.gitee.wsl.android.ui.ext.ActivityStack.foregroundObserver.invoke(com.gitee.wsl.android.ui.ext.ActivityStack.isForeground())
                } else if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.size == 1) {
                    /**
                     * @see activityMap
                     */
                    val value = com.gitee.wsl.android.ui.ext.ActivityStack.activityMap[com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.keys.first()]
                    if (value != null && value == true) {
                        com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.clear()
                    }
                    com.gitee.wsl.android.ui.ext.ActivityStack.foregroundObserver.invoke(com.gitee.wsl.android.ui.ext.ActivityStack.isForeground())
                }

                if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.isEmpty() && com.gitee.wsl.android.ui.ext.ActivityStack.isForceClose) {
                    com.gitee.wsl.android.ui.ext.ActivityStack.isForceClose = false
                    com.gitee.wsl.android.ui.ext.ActivityStack.killApp()
                }
            }

            override fun onActivityStopped(activity: Activity) {
                com.gitee.wsl.android.ui.ext.ActivityStack.activityMap[activity] = true
                if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.size == 1) {
                    com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.remove(activity)
                    com.gitee.wsl.android.ui.ext.ActivityStack.foregroundObserver.invoke(com.gitee.wsl.android.ui.ext.ActivityStack.isForeground())
                }
            }

            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
            }

            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                com.gitee.wsl.android.ui.ext.ActivityStack.activityMap[activity] = false
                if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.size == 1) {
                    com.gitee.wsl.android.ui.ext.ActivityStack.foregroundObserver.invoke(true)
                }
            }
        }
    }

    fun registerObserver( observer: (Boolean) -> Unit) {
        com.gitee.wsl.android.ui.ext.ActivityStack.foregroundObserver = observer
    }

    /**
     * 注册Activity Lifecycle callback.
     * @param observer 是否在前台的监听器，注意：只判断Activity是不是前台可见的.
     */
    @JvmStatic
    fun registerCallback(app: Application, observer: (Boolean) -> Unit = { }) {
        if(com.gitee.wsl.android.ui.ext.ActivityStack.isInited) return
        com.gitee.wsl.android.ui.ext.ActivityStack.foregroundObserver = observer
        app.registerActivityLifecycleCallbacks(com.gitee.wsl.android.ui.ext.ActivityStack.callback)
        com.gitee.wsl.android.ui.ext.ActivityStack.isInited = true
    }

    /**
     * 取消注册Activity Lifecycle callback.
     */
    @JvmStatic
    fun unregisterCallback(app: Application) {
        if(!com.gitee.wsl.android.ui.ext.ActivityStack.isInited) return
        com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.clear()
        app.unregisterActivityLifecycleCallbacks(com.gitee.wsl.android.ui.ext.ActivityStack.callback)
        com.gitee.wsl.android.ui.ext.ActivityStack.isInited = false
    }

    /**
     * 返回已启动的Activity数量.
     */
    @JvmStatic
    fun getRunningActivityCount(): Int {
        return com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.size
    }

    /**
     * 判断Activity是否在前台
     */
    @JvmStatic
    fun isForeground(): Boolean {
        return com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.isNotEmpty()
    }

    /**
     * 获取当前Activity.
     */
    @JvmStatic
    fun getCurrentActivity(): Activity? {
        if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.isEmpty()) {
            return null
        }

        return com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.keys.last()
    }

    /**
     * 关闭[clazz] Activity.
     */
    @JvmStatic
    fun finish(clazz: KClass<out Activity>) {
        com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.keys.reversed().forEach {
            if (it::class == clazz) {
                it.finish()
                return
            }
        }
    }

    /**
     * 关闭类名为[name]的Activity.
     */
    /*@JvmStatic
    fun finishByName(name: String) {
        for (activity in activityMap.keys.reversed()) {
            if (activity.javaClass == name) {
                activity.finish()
            }
        }
    }*/

    /**
     * 关闭简单类名为[name]的Activity.
     */
    /*@JvmStatic
    fun finishBySimpleName(name: String) {
        for (activity in activityMap.keys.reversed()) {
            if (activity.javaClass.simpleName == name) {
                activity.finish()
            }
        }
    }*/

    /**
     * 关闭当前Activity.
     */
    @JvmStatic
    fun finishCurrent() {
        if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.size > 0) {
            com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.keys.last().finish()
        }
    }

    /**
     * 关闭所有Activity.
     */
    @JvmStatic
    fun finishAll() {
        com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.keys.reversed().forEach {
            it.finish()
        }
    }

    /**
     * 关闭除[clazz]外的所有Activity.
     */
    @JvmStatic
    fun finishAllExcept(clazz: KClass<out Activity>) {
        com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.keys.reversed().forEach {
            if (it::class != clazz) {
                it.finish()
            }
        }
    }

    /**
     * 关闭除类名为[name]外的所有Activity.
     */
    /*@JvmStatic
    fun finishAllExceptName(name: String) {
        activityMap.keys.reversed().forEach {
            if (it.javaClass.name != name) {
                it.finish()
            }
        }
    }*/

    /**
     * 关闭除简单类名为[name]外的所有Activity.
     * @see [Class.getSimpleName]
     */
    @JvmStatic
    /*fun finishAllExceptSimpleName(name: String) {
        activityMap.keys.reversed().forEach {
            if (it.javaClass.simpleName != name) {
                it.finish()
            }
        }
    }*/

    /**
     * 启动[clazz],[map]是附带参数.
     */
    fun start(clazz: Class<out Activity>,context:Context = application, map: Map<String, Serializable>? = null) {
        val currentActivity = com.gitee.wsl.android.ui.ext.ActivityStack.getCurrentActivity()
        val intent = Intent(context, clazz)
        map?.map {
            intent.putExtra(it.key, it.value)
        }

        if (currentActivity == null) {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)
        } else {
            currentActivity.startActivity(intent)
        }
    }

    /**
     * 通过[intent]启动Activity.
     */
    @JvmStatic
    fun start(intent: Intent,context:Context = application) {
        intent.component?.let {
            val currentActivity = com.gitee.wsl.android.ui.ext.ActivityStack.getCurrentActivity()
            if (currentActivity == null) {
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                context.startActivity(intent)
            } else {
                currentActivity.startActivity(intent)
            }
        }
    }

    /**
     * 启动[clazz], [map]是附带参数，并且关闭其他所有Activity.
     */
    /*@JvmStatic
    fun startAndFinishOthers(clazz: Class<out Activity>,context:Context = application, map: Map<String, Serializable>? = null) {
        start(clazz,context, map)
        finishAllExcept(clazz)
    }*/

    /**
     * [intent]方式启动Activity，并且关闭其他所有Activity.
     */
    /*@JvmStatic
    fun startAndFinishOthers(intent: Intent,context:Context = application) {
        intent.component?.let {
            start(intent,context)
            finishAllExcept(Class.forName(it.className) as Class<out Activity>)
        }
    }*/

    /**
     * 关闭除顶部Activity外的其他所有activity.
     * @since 3.1.0 修复了死循环问题
     */
    @JvmStatic
    fun finishExceptTop() {
        if (com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.isNotEmpty()) {
            com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.keys.toList().subList(0, com.gitee.wsl.android.ui.ext.ActivityStack.activityMap.size - 1).forEach {
                it.finish()
            }
        }
    }


    /**
     * 关闭所有页面后，终止进程。推荐使用这个方法终止进程.
     */
    @JvmStatic
    fun finishAllAndKillApp() {
        com.gitee.wsl.android.ui.ext.ActivityStack.isForceClose = true
        com.gitee.wsl.android.ui.ext.ActivityStack.finishAll()
    }

    /**
     * 强杀进程. 慎重使用：直接调用这个方法可能有app自动重新打开的问题.
     * @since 3.0.1
     */
    @JvmStatic
    fun killApp() {
        Process.killProcess(Process.myPid())
        exitProcess(0)
    }
}

fun com.gitee.wsl.android.ui.ext.ApplicationScope.ableActivityStack(){
    com.gitee.wsl.android.ui.ext.ActivityStack.registerCallback(application)
}


fun ComponentActivity.pressBackTwiceToExitApp(
    delayMillis: Long = 2000,
    owner: LifecycleOwner = this,
    onFirstBackPressed: () -> Unit,
    finish:()->Unit
) =
    onBackPressedDispatcher.addCallback(owner, object : OnBackPressedCallback(true) {
        private var lastBackTime: Long = 0
        override fun handleOnBackPressed() {
            lastBackTime=twiceCheckDelayCallBack(lastBackTime,delayMillis, onFirstBackPressed, finish)
        }
    })

fun ComponentActivity.pressBackToNotExitApp(owner: LifecycleOwner = this) =
    doOnBackPressed(owner) { moveTaskToBack(false) }

fun ComponentActivity.doOnBackPressed(owner: LifecycleOwner = this, onBackPressed: () -> Unit) =
    onBackPressedDispatcher.addCallback(owner, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() = onBackPressed()
    })

inline fun <reified T:Activity> ComponentActivity.startActivity(vararg params: Pair<String, *>){
    startActivity(intentOf<T>(*params))
}

inline fun <reified T:Activity> Fragment.startActivity(vararg params: Pair<String, *>){
    startActivity(requireContext().intentOf<T>(*params))
}

fun Activity.finishForResult(vararg params: Pair<String, *>) {
    setResult(Activity.RESULT_OK, intentOf<Activity>(*params))
    finish()
}

fun Activity.activateLockScreen() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        setShowWhenLocked(true)
        setTurnScreenOn(true)
    } else {
        window.addFlags(
            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
        )
    }

    with(getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            requestDismissKeyguard(this@activateLockScreen, null)
        }
    }
}

fun Activity.deactivateLockScreen() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        setShowWhenLocked(false)
        setTurnScreenOn(false)
    } else {
        window.clearFlags(
            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
        )
    }
}

fun <T: View> Activity.lazyViewById(viewId:Int):Lazy<T>{
    return lazy{
        findViewById(viewId)
    }
}

/**
 * 使用时必须保证调用了 onCreateView 生成根view
 *    可以在 onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) 中调用初始化
 */
fun <T: View> Fragment.lazyViewById(viewId:Int):Lazy<T>{
    return lazy{
        requireView().findViewById(viewId)
    }
}

val globalFullyDrawnReporter:FullyDrawnReporter by lazy{ FullyDrawnReporter(executor = Scheduler.ioPool){ Timber.d("FullyDrawnReporter do...")}}

//reportWhenComplete{}封装：等待方法体中的逻辑执行完毕之后才去调用Activity.reportFullyDrawn()统计冷启动耗时：
suspend fun K.reportWhenComplete(block: suspend () -> Unit) = com.gitee.wsl.android.ui.ext.globalFullyDrawnReporter.reportWhenComplete(block)